# File: basicX.py
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtWidgets import QApplication

import autogen.basic as basic
import common
import datavisualX
from common import *


class SingleAxisMeasurerTask(AbstractMeasurerTask):
    def __init__(self, hm: HallMachine, axis: Axis, step: float, target: float,
                 recorder: Recorder, timer_to_connect_with: QTimer = common.DEFAULT_MAIN_TIMER):
        super(SingleAxisMeasurerTask, self).__init__()
        self.hm = hm
        self.hm_helper = HallMachineAxisHelper(self.hm)
        self.axis = axis
        self.step = step
        self.timer = timer_to_connect_with
        self.target = target
        self.__start_pt = self.hm_helper.get_pos(self.axis)
        self.target_s = abs(target - self.hm_helper.get_pos(self.axis))
        self.i = 0  # 表示当前应该写第几行
        self.done = False  # 表示此任务已经结束
        self.recorder = recorder

    def __on_timer(self, ):
        if self.done:
            return self.stop()
        s = abs(self.hm_helper.get_pos(self.axis) - self.__start_pt)
        if s >= self.step * self.i or self.hm_helper.all_axis_stopped():
            self.recorder.push_back(self.hm)
            self.i += 1
            print("self.i = %s\ts = %s\ttarget_s = %s" % (self.i, s, self.target_s))
            self.sig_raw_data_updated.emit(self.recorder)
            self.sig_mean_data_updated.emit(self.recorder)
            if s > self.target_s:
                return self.stop()  # 记录终点

    def start(self):
        self.timer.timeout.connect(
            self.__on_timer
        )
        self.__on_timer()  # 记录起点
        self.hm_helper.d_jog_to[self.axis](self.target)

    def stop(self):
        self.done = True
        self.recorder.to_csv()
        self.timer.timeout.disconnect(self.__on_timer)
        self.sig_mean_data_done.emit(self.recorder)
        self.sig_raw_data_done.emit(self.recorder)


class BasicX(basic.Ui_Widget):
    X_MAX, Y_MAX, Z_MAX = BOUNDINGS[Axis.X], BOUNDINGS[Axis.Y], BOUNDINGS[Axis.Z]

    def __init__(self, hm: common.HallMachine, timer: common.DataExchangerTimer, parent: QtWidgets.QWidget,
                 data_visualX: datavisualX.DataVisualX = None):
        pass
        super().__init__()
        self.hm = hm
        self.hmhelper = HallMachineAxisHelper(self.hm)
        self.__parent = parent
        self.setupUi(self.__parent)
        self.__gui_axis_name_dict = {
            "Z轴": Axis.Z,
            "X轴": Axis.X,
            "Y轴": Axis.Y,
            "A轴（慎用）": Axis.A,
            "C轴（慎用）": Axis.C,
        }
        __keys = list(self.__gui_axis_name_dict.keys())
        for i in range(self.comboBox_choose_axis.count()):
            self.comboBox_choose_axis.setItemText(i, __keys[i])
        self.__timer_to_update_all = timer
        self.data_visualX = data_visualX
        self.__axis = self.__get_choosed_axis()
        self.__single_axis_measurer: SingleAxisMeasurerTask = None
        self.__set_validator()
        self.connect_all()

    def set_data_visualX(self, data_visual_X: datavisualX.DataVisualX):
        self.data_visualX = data_visual_X

    def connect_all(self):
        self.pushButton_laser_ref_pt.clicked.connect(self.hm.set_laser_ref_pt)
        self.pushButton_apply.clicked.connect(self.__on_apply)
        self.__connect_set_manual()
        self.__connect_stop()
        self.__connect_return_to_0()
        self.__timer_to_update_all.timeout.connect(self.__on_timer)
        self.__connect_set_speed()
        self.comboBox_choose_axis.currentTextChanged.connect(self.__on_axis_comboBoxChanged)

    def __on_axis_comboBoxChanged(self):
        self.__axis: Axis = self.__get_choosed_axis()
        if self.__axis in {Axis.A, Axis.C}:
            self.__hide_unsupported(True)
        else:
            self.__hide_unsupported(False)

    def __set_validator(self):
        self.lineEdit_target_pos_mm_or_degree.setValidator(QtGui.QDoubleValidator())
        self.lineEdit_step_length.setValidator(QtGui.QDoubleValidator())

    def __on_timer(self):
        self.lineEdit_axis_realtime_pos.setText(str(self.hmhelper.get_pos(self.__axis)))
        if self.lineEdit_axis_realtime_speed.isVisible():
            self.lineEdit_axis_realtime_speed.setText(str(self.hmhelper.d_get_speed[self.__axis]()))

    def __hide_unsupported(self, on):
        if on:
            self.horizontalSlider_speed.hide()
            self.lineEdit_axis_realtime_speed.hide()
        else:
            self.horizontalSlider_speed.show()
            self.lineEdit_axis_realtime_speed.show()

    def __get_choosed_axis(self) -> Axis:
        return self.__gui_axis_name_dict[self.comboBox_choose_axis.currentText()]

    def __connect_set_speed(self):
        def set_speed():
            axis = self.__get_choosed_axis()
            ui_max_value = self.horizontalSlider_speed.maximum()
            ratio = self.horizontalSlider_speed.value() / ui_max_value
            speed = int(ratio * MAX_SPEED[axis])
            self.label_target_speed.setText(str(speed))

        self.horizontalSlider_speed.valueChanged.connect(set_speed)

    def __connect_stop(self):
        self.pushButton_stop.clicked.connect(self.__on_stop)

    def __on_stop(self):
        self.hmhelper.d_stop[self.__get_choosed_axis()]()
        if self.__single_axis_measurer:
            self.__single_axis_measurer.stop()

    def __connect_return_to_0(self):
        self.pushButton_ret_to_0.clicked.connect(lambda: self.hmhelper.d_find_0[self.__get_choosed_axis()]())

    def __connect_set_manual(self):
        self.checkBox_manual_mode.toggled.connect(
            self.hm.set_manual
        )

    def __on_apply(self):
        target = float(self.lineEdit_target_pos_mm_or_degree.text())
        axis = self.__get_choosed_axis()
        step = float(self.lineEdit_step_length.text())
        self.__single_axis_measurer = \
            SingleAxisMeasurerTask(self.hm, axis, step, target,
                                   Recorder(
                                       common.Recorder.DEFAULT_RECORD_DIR,
                                       common.Recorder.DEFAULT_PREFIX),
                                   self.__timer_to_update_all)
        if self.data_visualX:
            self.data_visualX.set_measurer(self.__single_axis_measurer)
        self.__single_axis_measurer.start()
        self.__single_axis_measurer.sig_raw_data_done.connect(self.__on_measurer_done)

    def __on_measurer_done(self):
        self.__single_axis_measurer = None


if __name__ == '__main__':
    app = QApplication([])
    stats = QtWidgets.QMainWindow()
    widget = QtWidgets.QWidget(stats)
    hm = common.HallMachine()
    BasicX(hm, common.DEFAULT_MAIN_TIMER, widget, )
    stats.setCentralWidget(widget)
    stats.show()
    sys.exit(app.exec_())
